from pinhole.datasource.utils import hexstr2str, str2hexstr
from pydantic.dataclasses import dataclass, Field
from pydantic.root_model import RootModel

from typing import List, Optional


@dataclass(repr=False)
class Outline:
    summary_id: int
    _model: str
    _content: str
    _keywords: List[str]

    outline_id: Optional[int] = Field(default=None)

    @property
    def model(self) -> str:
        return hexstr2str(self._model)

    @property
    def content(self) -> str:
        return hexstr2str(self._content)

    @property
    def keywords(self) -> List[str]:
        return [hexstr2str(_kw) for _kw in self._keywords]

    @classmethod
    def build(cls, summary_id: int, model: str, content: str, keywords: List[str]) -> 'Outline':
        _model = str2hexstr(model)
        _content = str2hexstr(content)
        _keywords = [str2hexstr(kw) for kw in keywords]
        return Outline(summary_id, _model, _content, _keywords)

    @classmethod
    def from_json(cls, content: str) -> 'Outline':
        return RootModel[Outline].model_validate(content).root


@dataclass(repr=False)
class Summary:
    # among the following two ids, only one should be present
    # while another should be empty
    document_id: int
    publication_id: int
    _model: str
    _content: str
    summary_id: Optional[int] = None

    def __repr__(self) -> str:
        return f"<Summary of document {self.document_id} />"

    @property
    def model(self) -> str:
        return hexstr2str(self._model)

    @property
    def content(self) -> str:
        return hexstr2str(self._content)

    @classmethod
    def build(cls, document_id: int, publication_id: int, model: str, publisher: str) -> 'Summary':
        if document_id >= 0 and publication_id >= 0:
            raise ValueError(f"invalid summary, one of document id and publication id should be -1")

        _model = str2hexstr(model)
        _publisher = str2hexstr(publisher)
        return Summary(document_id, publication_id, _model, _publisher)

    @classmethod
    def from_json(cls, content: str) -> 'Summary':
        return RootModel[Summary].model_validate(content).root


@dataclass(repr=False)
class SummaryRef:
    summary_id: int
    document_id: Optional[int]
    publication_id: Optional[int]

    @classmethod
    def from_json(cls, content: str) -> 'SummaryRef':
        return RootModel[SummaryRef].model_validate(content).root
